<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet  version="2.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:ccts="urn:un:unece:uncefact:documentation:standard:CoreComponentsTechnicalSpecification:2"
	xmlns="http://www.w3.org/1999/xhtml">
	
	<xsl:import href="GlobalVars.xsl"/>
	<xsl:import href="GlobalTemplates.xsl"/>
	
	<xsl:output method="text" name="textFormat" indent="yes"/>
	
	<xsl:template name="generate-style" >
		<xsl:param name="element.root" />
		<xsl:param name="element.root.type" />
		
		<xsl:element name="link">
			<xsl:attribute name="href">style.css</xsl:attribute>
			<xsl:attribute name="rel">stylesheet</xsl:attribute>
			<xsl:attribute name="type">text/css</xsl:attribute>
		</xsl:element>
		
		<xsl:variable name="root" 
			select="document( $global.schema.root )//xsd:complexType[@name = substring-after( $element.root.type, ':') ]"/>
		
		<!--
			Create a pretty css file that contains the look and feel for the form.
		-->
		<xsl:result-document href="style.css" format="textFormat">
			<xsl:value-of>@namespace xf url("http://www.w3.org/2002/xforms");
			
</xsl:value-of>
			<xsl:call-template name="GenerateGeneralStyle" />
			<xsl:variable name="den" select="$root/xsd:annotation/xsd:documentation/ccts:DictionaryEntryName" />
			<xsl:call-template name="HandleCoreComponent">
				<xsl:with-param name="DEN" select="$den"/>
			</xsl:call-template>
			<xsl:call-template name="GenerateElementStyles">
				<xsl:with-param name="element.type" select="$element.root.type" />
				<xsl:with-param name="element.schema" select="$global.schema.root" />
			</xsl:call-template>
		</xsl:result-document>		
	</xsl:template>
	
	<xsl:template name="GenerateGeneralStyle">
		<xsl:for-each select="document( $global.file.annotations )/annotations/general-style/element">
			<xsl:choose>
				<xsl:when test="@name">
					<xsl:value-of select="concat( @name, ' {' )"/>
					<xsl:call-template name="NewLine" />
				</xsl:when>
				<xsl:otherwise>
					<xsl:call-template name="PrintCSSClassStart">
						<xsl:with-param name="class" select="@class"/>
					</xsl:call-template>
				</xsl:otherwise>
			</xsl:choose>
			<xsl:for-each select="child::node()">
				<xsl:if test="name()" >
					<xsl:call-template name="PrintProperty">
						<xsl:with-param name="property" select="name()" />
						<xsl:with-param name="property.value" select="." />
					</xsl:call-template>
				</xsl:if>
			</xsl:for-each>
			<xsl:call-template name="PrintCSSClassEnd" />
		</xsl:for-each>
	</xsl:template>
	
	<xsl:template name="GenerateElementStyles">
		<xsl:param name="element.type" />
		<xsl:param name="element.schema" />
		
		<xsl:variable name="element.children">
			<xsl:call-template name="GetChildElements">
				<xsl:with-param name="parent" select="substring-after( $element.type, ':' )" />
				<xsl:with-param name="parent.schema" select="$element.schema" />
			</xsl:call-template>			
		</xsl:variable>
		
		<xsl:for-each select="$element.children/xsd:element">
			<xsl:choose>
				<xsl:when test="xsd:annotation/xsd:documentation/ccts:Acronym = 'BBIE'">
					<xsl:variable name="element.type.schema">
						<xsl:call-template name="GetDataTypeDocument">
							<xsl:with-param name="element.type" select="@type" />
							<xsl:with-param name="element.schema" select="$element.schema" />
						</xsl:call-template>
					</xsl:variable>
					<xsl:call-template name="HandleCoreComponent">
						<xsl:with-param name="DEN" select="xsd:annotation/xsd:documentation/ccts:DictionaryEntryName"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:otherwise>
					<xsl:call-template name="HandleCoreComponent">
						<xsl:with-param name="DEN" select="xsd:annotation/xsd:documentation/ccts:DictionaryEntryName"/>
					</xsl:call-template>
					
					<xsl:variable name="element.child.ns" 
						select="namespace-uri-for-prefix( substring-before( @type, ':' ), . )"/>
					<xsl:variable name="element.ns" select="if( $element.schema = '' ) 
						then document( $global.schema.root )/xsd:schema/@targetNamespace
						else document( $element.schema )/xsd:schema/@targetNamespace"/>
					<xsl:choose>
						<!-- 
							Test if the child element is declared in the same namespace as it's parent. If not then
							we'll have to look in which document the namespace (and thus the element) is declared.
							Also we'll have to look which prefix is used for that namespace.
						-->
						<xsl:when test="$element.ns != $element.child.ns">
							<xsl:variable name="element.type.schema">
								<xsl:call-template name="GetDataTypeDocument">
									<xsl:with-param name="element.type" select="@type" />
									<xsl:with-param name="element.schema" select="$element.schema" />
								</xsl:call-template>
							</xsl:variable>
							
							<xsl:call-template name="GenerateElementStyles">
								<xsl:with-param name="element.type" select="@type"/>
								<xsl:with-param name="element.schema" select="$element.type.schema" />
							</xsl:call-template>
						</xsl:when>
						<!-- 
							The element is declared in the same document as his parent.
						-->
						<xsl:otherwise>
							<xsl:call-template name="GenerateElementStyles">
								<xsl:with-param name="element.type" select="@type"/>
								<xsl:with-param name="element.schema" select="$element.schema" />
							</xsl:call-template>
						</xsl:otherwise>
					</xsl:choose>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:for-each>
	</xsl:template>
	
	<xsl:template name="HandleCoreComponent">
		<xsl:param name="DEN" />
		<xsl:call-template name="PrintCSSClassStart">
			<xsl:with-param name="class" select="$DEN" />
		</xsl:call-template>
		<xsl:call-template name="ReadProperties">
			<xsl:with-param name="DEN" select="$DEN" />
		</xsl:call-template>
		<xsl:call-template name="PrintCSSClassEnd" />

		<!-- insert here styling for supplementary components -->
		
		<xsl:variable name="supp" select="concat($DEN,'SuppToggle')"/>
		<xsl:choose>
			<xsl:when test="ends-with($DEN,'Code')">
				<xsl:call-template name="PrintCSSClassStart">
				<xsl:with-param name="class" select="$supp" />
				</xsl:call-template>
				<xsl:call-template name="ReadProperties">
				<xsl:with-param name="DEN" select="$supp" />
				</xsl:call-template>
				<xsl:call-template name="PrintCSSClassEnd" />
			</xsl:when>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template name="ReadProperties">
		<xsl:param name="DEN" />
		
		<xsl:for-each 
			select="document( $global.file.annotations )/annotations/supported-properties/property">
			<xsl:variable name="property" select="." />
			
			<xsl:variable name="property.value">
				<xsl:call-template name="FindPropertyValue">
					<xsl:with-param name="den.current" select="$DEN" />
					<xsl:with-param name="den.start" select="$DEN" />
					<xsl:with-param name="property" select="$property" />
				</xsl:call-template>
			</xsl:variable>
			
			<!-- Only if a value is found we have to write it to the css file -->
			<xsl:if test="not( $property.value ='' )">

				<xsl:variable name="property.value.definition">
					<xsl:call-template name="FindPropertyValueDefinition">
						<xsl:with-param name="property" select="$property"/>
						<xsl:with-param name="property.value" select="$property.value" />
						<xsl:with-param name="den" select="$DEN"/>
					</xsl:call-template>
				</xsl:variable>

				<xsl:choose>
					<xsl:when test="$property.value.definition and $property.value.definition != '' ">
						<xsl:call-template name="PrintProperty">
							<xsl:with-param name="property" select="$property" />
							<xsl:with-param name="property.value" select="$property.value.definition" />
						</xsl:call-template>
					</xsl:when>
					<xsl:otherwise>
						<xsl:value-of select="error( QName( 'e', 'e' ), concat(
							'No definition found for property value: ', $property.value, ' of property: ', $property, ' from element: ', $DEN ) )" />
					</xsl:otherwise>
				</xsl:choose>
			</xsl:if>
		</xsl:for-each>
	</xsl:template>
	
	<xsl:template name="FindPropertyValue">
		<xsl:param name="den.current" />
		<xsl:param name="den.start" />
		<xsl:param name="property" />
		
		<xsl:variable name="den.settings" 
			select="document( $global.file.annotations )/annotations/core-component[
			@den = $den.current]/component-settings" />
		
		<xsl:variable name="property.value" >
			<xsl:for-each select="$den.settings/descendant::*">
				<xsl:variable name="name" select="name()" />
				<xsl:if test="$name = $property">
					<xsl:value-of select="@value" />
				</xsl:if>
			</xsl:for-each>
		</xsl:variable>
		
		<xsl:choose>
			<xsl:when test="$property.value =''">
				<xsl:choose>
					<xsl:when test="not( contains( $den.current, '. Type' ) )
						and not( contains( $den.current, '. Details' ) )
						and contains( substring-before( $den.current,'.' ), '_ ' ) ">
						
						<xsl:call-template name="FindPropertyValue">
							<xsl:with-param name="den.current" 
								select="concat( substring-after( substring-before( $den.current,'.' ), '_ ' )
								,'. ', substring-after( $den.current,'. ' ) )"/>
							<xsl:with-param name="den.start" select="$den.start"/>
							<xsl:with-param name="property" select="$property"/>
						</xsl:call-template>
					</xsl:when>
					
					<xsl:when test="not( contains( $den.current,'. Type' ) ) 
						and not( contains( $den.current, 'Details' ) )
						and contains( substring-before( substring-after( $den.current, '. ' ), '. ' ),'_' )">
						
						<xsl:call-template name="FindPropertyValue">
							<xsl:with-param name="den.current" 
								select="concat( substring-before( $den.start,'.' ), '.',
								substring-after( substring-after( $den.current,'.' ), '_' ) )"/>
							<xsl:with-param name="den.start" select="$den.start" />
							<xsl:with-param name="property" select="$property"/>
						</xsl:call-template>
					</xsl:when>
					
					<xsl:when test="not( contains( $den.current, '. Type' ) )
						and not( contains( $den.current, '. Details' ) )">
						
						<xsl:call-template name="FindPropertyValue">
							<xsl:with-param name="den.current"
								select="concat( substring-after( substring-after( $den.current, '. ' )
								, '. ' ), '. Details' )"/>
							<xsl:with-param name="den.start" select="$den.start"/>
							<xsl:with-param name="property" select="$property"/>
						</xsl:call-template>
					</xsl:when>
					
					<xsl:when test="contains( $den.current,'. Details' )">
						<xsl:call-template name="FindPropertyValue">
							<xsl:with-param name="den.current" 
								select="concat( substring-before( $den.current, '.' ), '. Type' )"/>
							<xsl:with-param name="den.start" select="$den.start"/>
							<xsl:with-param name="property" select="$property"/>
						</xsl:call-template>
					</xsl:when>
					
					<xsl:when test="contains( $den.current, '. Type' ) and contains( $den.current, '_' ) 
						and matches( $den.current, '[.]*\.[.]*\.[.]*' )">
						<xsl:call-template name="FindPropertyValue">
							<xsl:with-param name="den.current" 
								select="concat( substring-before( $den.start,'.')
								, '. ', substring-before( substring-after( $den.start, '. ' ), '.' )
								, '. ', substring-after( substring-before( $den.current, '.' ), '_ ' ) )"/>
							<xsl:with-param name="den.start" select="$den.start"/>
							<xsl:with-param name="property" select="$property"/>
						</xsl:call-template>
					</xsl:when>
					
					<xsl:when test="contains( $den.current, '. Type' ) and contains( $den.current, '_' )">
						<xsl:call-template name="FindPropertyValue">
							<xsl:with-param name="den.current" 
								select="concat( substring-after( substring-before( $den.current,'.' ), '_ ' )
								, '. ', substring-after( $den.current, '. ' ) )"/>
							<xsl:with-param name="den.start" select="$den.start"/>
							<xsl:with-param name="property" select="$property"/>
						</xsl:call-template>
					</xsl:when>
					
					<xsl:otherwise>
						<!-- At this point we have an unqualified datatype or an unqualified ABIE -->
					</xsl:otherwise>
				</xsl:choose>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$property.value" />
			</xsl:otherwise>
		</xsl:choose>	
	</xsl:template>
	
	<xsl:template name="FindPropertyValueDefinition">
		<xsl:param name="property" as="xsd:string" required="yes"/>
		<xsl:param name="property.value" as="xsd:string" required="yes"/>
		<xsl:param name="den" as="xsd:string" required="yes"/>
		
		<xsl:variable name="den.document.settings" 
			select="document( $global.file.annotations )/annotations/core-component[
			@den = $den]/document-settings" />
		
		<xsl:variable name="parent.den">
			<xsl:call-template name="GetParentDen">
				<xsl:with-param name="den.search" select="$den" />
				<xsl:with-param name="element.den" select="$global.element.root.den"/>
				<xsl:with-param name="element.type" select="$global.element.root.type" />
				<xsl:with-param name="element.schema" select="$global.schema.root" />
			</xsl:call-template>
		</xsl:variable>
		
		<xsl:choose>
			<xsl:when test="not( $den.document.settings ) and $parent.den = '' ">
				<!-- No Property definition found -->
			</xsl:when>
			<!-- 
				When there are no document settings but there is a parent we look at 
				the parent to discover the definition.
			-->
			<xsl:when test="not( $den.document.settings ) and $parent.den != '' ">
				<xsl:call-template name="FindPropertyValueDefinition">
					<xsl:with-param name="property" select="$property"/>
					<xsl:with-param name="property.value" select="$property.value"/>
					<xsl:with-param name="den" select="$parent.den"/>
				</xsl:call-template>
			</xsl:when>
			<!-- 
				When there are document-settings but the definition is not found and there is a 
				parent we look at the parent to discover the definition.
			-->
			<xsl:when test="$den.document.settings">
				<xsl:variable name="property.value.definition"
					select="$den.document.settings/node()
					[name() = $property]/node()
					[name() = $property.value]/@value" />
				
				<xsl:choose>
					<xsl:when test="not( $property.value.definition ) and $parent.den != ''">
						<xsl:call-template name="FindPropertyValueDefinition">
							<xsl:with-param name="property" select="$property"/>
							<xsl:with-param name="property.value" select="$property.value"/>
							<xsl:with-param name="den" select="$parent.den"/>
						</xsl:call-template>
					</xsl:when>
					<xsl:otherwise>
						<xsl:value-of select="$property.value.definition" />
					</xsl:otherwise>
				</xsl:choose>
			</xsl:when>
			
			<!--
				TODO: If nothing found here we are in the root element of the message. We should walk up the tree
				if nessessary. e.g. Purchase_ Order. Details -> Order. Details
			-->
		</xsl:choose>
	</xsl:template>
	
	<!-- Some output formatting templates -->
	<xsl:template name="NewLine">
		<xsl:text>
</xsl:text>
	</xsl:template>
	
	<xsl:template name="PrintCSSClassStart">
		<xsl:param name="class" />
		<xsl:value-of select="concat( '.', replace( replace( $class, ' ', '' ), '\.', '__' ),' {' )" />
		<xsl:call-template name="NewLine" />
	</xsl:template>
	
	<xsl:template name="PrintProperty">
		<xsl:param name="property" />
		<xsl:param name="property.value" />
		
		<xsl:text>    </xsl:text>
		<xsl:value-of select="$property" />
		<xsl:text>: </xsl:text>
		<xsl:value-of select="$property.value" />
		<xsl:text>;</xsl:text>
		<xsl:call-template name="NewLine" />
	</xsl:template>
	
	<xsl:template name="PrintCSSClassEnd">
		<xsl:text>}</xsl:text>
		<xsl:call-template name="NewLine" />
		<xsl:call-template name="NewLine" />
	</xsl:template>
</xsl:stylesheet>